package com.sp.fresh_produce.service.impl;

import com.github.pagehelper.PageInfo;
import com.google.zxing.WriterException;
import com.sp.fresh_produce.common.Constant;
import com.sp.fresh_produce.controller.dto.VO.CartVO;
import com.sp.fresh_produce.controller.dto.VO.OrderItemVO;
import com.sp.fresh_produce.controller.dto.VO.OrderVO;
import com.sp.fresh_produce.controller.dto.req.CreateOrderReq;
import com.sp.fresh_produce.ex.CustomException;
import com.sp.fresh_produce.ex.ExceptionCodeEnum;
import com.sp.fresh_produce.model.dao.CartMapper;
import com.sp.fresh_produce.model.dao.OrderItemMapper;
import com.sp.fresh_produce.model.dao.OrderMapper;
import com.sp.fresh_produce.model.dao.ProductMapper;
import com.sp.fresh_produce.model.pojo.Order;
import com.sp.fresh_produce.model.pojo.OrderItem;
import com.sp.fresh_produce.model.pojo.Product;
import com.sp.fresh_produce.service.OrderService;
import com.sp.fresh_produce.util.OrderCodeFactory;
import com.sp.fresh_produce.util.QRCodeGenerator;
import com.sp.fresh_produce.util.SessionUtils;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 订单服务实现类
 */
@Service
public class OrderServiceImpl implements OrderService {

    @Autowired
    private CartMapper cartMapper;
    @Autowired
    private ProductMapper productMapper;
    @Autowired
    private OrderMapper orderMapper;
    @Autowired
    private OrderItemMapper orderItemMapper;

    @Value("${file.upload.ip}")
    String ip;

    @Override
    /**
     *
     * 创建订单
     */
    // 数据库事务
    @Transactional(rollbackFor = Exception.class)
    public String createOrder(Integer userId, CreateOrderReq createOrderReq) {
        // 拿到用户id（来自控制器会话）
        // 从购物车查找已经勾选的商品
        List<CartVO> cartList = cartMapper.selectCartByUserIdList(userId)
                .stream()
                .filter(c -> Objects.equals(c.getSelected(), Constant.CartChecked.CHECKED))
                .collect(Collectors.toList());
        // 如果已经勾选的商品为空，报错
        if (cartList == null || cartList.isEmpty()) {
            throw getCustomException(ExceptionCodeEnum.CART_EMPTY);
        }
        // 判断商品是否存在，上下架状态、库存
        validSaleStatusAndStock(cartList);
        // 把购物车对象转为订单item对象
        List<OrderItem> orderItems = cartVOListToOrderItemList(cartList);
        // 扣库存
        for (OrderItem orderItem : orderItems) {
            Product product = productMapper.selectByPrimaryKey(orderItem.getProductId());
            int stock = product.getStock() - orderItem.getQuantity();
            if (stock < 0) {
                throw getCustomException(ExceptionCodeEnum.PRODUCT_STOCK_ERROR);
            }
            product.setStock(stock);
            productMapper.updateByPrimaryKeySelective(product);
        }
        // 把购物车中的已勾选商品删除
        clearCart(cartList);
        // 生成订单号，有独立的规则
        Order order = new Order();
        String orderNum = OrderCodeFactory.getOrderCode(Long.valueOf(userId));
        order.setOrderNo(orderNum);
        order.setUserId(userId);
        order.setTotalPrice(totalPrice(orderItems));
        order.setReceiverName(createOrderReq.getReceiverName());
        order.setReceiverMobile(createOrderReq.getReceiverMobile());
        order.setReceiverAddress(createOrderReq.getReceiverAddress());
        order.setOrderStatus(Constant.OrderStatusEnum.NOT_PAID.getCode());
        order.setPostage(0);
        order.setPaymentType(1);

        orderMapper.insertSelective(order);
        // 循环保存每个商品到order_item表
        for (OrderItem orderItem : orderItems) {
            orderItem.setOrderNo(order.getOrderNo());
            orderItemMapper.insertSelective(orderItem);
        }
        // 把结果返回
        return orderNum;
    }


    /**
     * 订单详情
     */
    @Override
    public OrderVO detail(String orderNo) {
        Order order = loadOrderOrThrow(orderNo);
        ensureOrderOwnedByCurrentUser(order);
        return getOrderVO(order);
    }

    /**
     * 获取订单VO
     */
    private OrderVO getOrderVO(Order order) {
        OrderVO orderVO = new OrderVO();
        BeanUtils.copyProperties(order, orderVO);
        // 获取订单对应的OrderItemVOList
        List<OrderItem> orderItemsList = orderItemMapper.selectByOrderNo(order.getOrderNo());
        List<OrderItemVO> orderItemVOList = new ArrayList<>();
        for (OrderItem orderItem : orderItemsList) {
            OrderItemVO orderItemVO = new OrderItemVO();
            BeanUtils.copyProperties(orderItem, orderItemVO);
            orderItemVOList.add(orderItemVO);
        }
        orderVO.setOrderItemVOList(orderItemVOList);
        orderVO.setOrderStatusName(Constant.OrderStatusEnum.codeOf(orderVO.getOrderStatus()).getValue());
        return orderVO;
    }

    /**
     * 取消订单
     */
    @Override
    public void cancel(String orderNo) {
        Order order = loadOrderOrThrow(orderNo);
        ensureOrderOwnedByCurrentUser(order);
        //  未付款才能取消订单
        if (order.getOrderStatus().equals(Constant.OrderStatusEnum.NOT_PAID.getCode())) {
            // 取消订单
            order.setOrderStatus(Constant.OrderStatusEnum.CANCELED.getCode());
            // 取消订单时间
            order.setEndTime(new Date());
            // 更新订单状态
            orderMapper.updateByPrimaryKeySelective(order);
        } else {
            throw getCustomException(ExceptionCodeEnum.ORDER_STATUS_ERROR);
        }
    }

    /**
     * 生成订单支付二维码
     *
     * @param orderNo 订单号
     * @return 二维码图片的访问地址
     * @throws IOException     IO异常
     * @throws WriterException 二维码生成异常
     */
    @Override
    public String qrcode(String orderNo) throws IOException, WriterException {
        // 从请求上下文中获取当前HTTP请求对象
        ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest httpServletRequest = null;
        if (servletRequestAttributes != null) {
            httpServletRequest = servletRequestAttributes.getRequest();
        }
        // 构造服务器地址（IP + 端口）
        String address = ip + ":" + httpServletRequest.getLocalPort();
        // 构造支付URL，格式为 http://ip:port/pay?orderNo=订单号
        String payUrl = "http://" + address + "/pay?orderNo=" + orderNo;
        // 调用工具类生成二维码图片并保存到指定路径
        // 图片保存路径为文件上传目录 + 订单号.png
        QRCodeGenerator.generateQRCode(payUrl, 350, 350, Constant.FILE_UPLOAD_DIR + orderNo + ".png");
        // 构造二维码图片的访问URL地址
        // 格式为 http://ip:port/images/订单号.png
        String pngAddress = "http://" + address + "/images/" + orderNo + ".png";
        // 返回二维码图片的访问地址
        return pngAddress;
    }

    /**
     * 后台订单管理列表
     */
    @Override
    public PageInfo listForAdmin(Integer pageNum, Integer pageSize) {
        // 查询所有订单列表
        List<Order> orderList = orderMapper.selectListForAdmin();
        // 把OrderList转换成OrderVOList
        List<OrderVO> orderVOList = orderList.stream().map(this::getOrderVO).collect(Collectors.toList());
        // 封装PageInfo
        PageInfo pageInfo = new PageInfo(orderList);
        // 填充OrderVOList到PageInfo
        pageInfo.setList(orderVOList);
        // 返回
        return pageInfo;
    }

    /**
     * 订单支付
     */
    @Override
    public void pay(String orderNo) {
        // 获取订单
        Order order = loadOrderOrThrow(orderNo);
        // 根据订单状态进行相应处理
        switch (Constant.OrderStatusEnum.codeOf(order.getOrderStatus())) {
            case NOT_PAID:
                // 修改订单状态为已付款
                order.setOrderStatus(Constant.OrderStatusEnum.PAID.getCode());
                // 修改订单付款时间
                order.setPayTime(new Date());
                // 更新订单
                orderMapper.updateByPrimaryKeySelective(order);
                break;
            // 已付款
            case PAID:
                throw getCustomException(ExceptionCodeEnum.ORDER_PAID);
            // 已发货
            case CANCELED:
                throw getCustomException(ExceptionCodeEnum.ORDER_CANCELLED);
            default:
                throw getCustomException(ExceptionCodeEnum.ORDER_STATUS_ERROR);
        }
    }

    /**
     * 管理员发货
     */
    @Override
    public void deliver(String orderNo) {
        // 获取订单
        Order order = loadOrderOrThrow(orderNo);
        // 根据订单状态进行相应处理
        switch (Constant.OrderStatusEnum.codeOf(order.getOrderStatus())) {
            case PAID:
                // 订单状态改为已发货
                order.setOrderStatus(Constant.OrderStatusEnum.DELIVERED.getCode());
                // 订单发货时间
                order.setDeliveryTime(new Date());
                // 订单更新
                orderMapper.updateByPrimaryKeySelective(order);
                break;
            case NOT_PAID:
                throw getCustomException(ExceptionCodeEnum.ORDER_NOT_PAY_YET);
            case DELIVERED:
                throw getCustomException(ExceptionCodeEnum.ORDER_ALREADY_DELIVERED);
            case FINISHED:
                throw getCustomException(ExceptionCodeEnum.ORDER_ALREADY_FINISHED);
            case CANCELED:
                throw getCustomException(ExceptionCodeEnum.ORDER_CANCELLED);
            default:
                throw getCustomException(ExceptionCodeEnum.ORDER_STATUS_ERROR);
        }
    }

    // 统计商品总价
    private Integer totalPrice(List<OrderItem> orderItems) {
        return orderItems.stream().mapToInt(OrderItem::getTotalPrice).sum();
    }

    // 把购物车中的已勾选商品删除
    private void clearCart(List<CartVO> cartList) {
        for (CartVO cartVO : cartList) {
            cartMapper.deleteByPrimaryKey(cartVO.getId());
        }
    }

    // 购物车对象转为订单item对象
    private List<OrderItem> cartVOListToOrderItemList(List<CartVO> cartList) {
        return cartList.stream().map(cartVO -> {
            OrderItem orderItem = new OrderItem();
            orderItem.setProductId(cartVO.getProductId());
            orderItem.setProductName(cartVO.getProductName());
            orderItem.setProductImg(cartVO.getProductImage());
            orderItem.setUnitPrice(cartVO.getPrice());
            orderItem.setQuantity(cartVO.getQuantity());
            orderItem.setTotalPrice(cartVO.getTotalPrice());
            return orderItem;
        }).collect(Collectors.toList());
    }

    // 判断商品是否存在，上下架状态、库存
    private void validSaleStatusAndStock(List<CartVO> cartList) {
        for (CartVO cartVO : cartList) {
            Product product = productMapper.selectByPrimaryKey(cartVO.getProductId());
            if (product == null || !product.getStatus().equals(Constant.ProductStatus.SALE)) {
                throw getCustomException(ExceptionCodeEnum.PRODUCT_NOT_EXIST);
            }
            if (cartVO.getQuantity() > product.getStock()) {
                throw getCustomException(ExceptionCodeEnum.PRODUCT_STOCK_ERROR);
            }
        }
    }

    // 获取自定义异常
    private static CustomException getCustomException(ExceptionCodeEnum orderNotExist) {
        return new CustomException(orderNotExist.getCode(), orderNotExist.getMessage());
    }

    // 从会话获取当前用户ID
    private Integer getCurrentUserIdFromSession() {
        return SessionUtils.getCurrentUserIdOrThrow();
    }

    // 加载订单，不存在则抛错
    private Order loadOrderOrThrow(String orderNo) {
        Order order = orderMapper.selectByOrderNo(orderNo);
        if (order == null) {
            throw getCustomException(ExceptionCodeEnum.ORDER_NOT_EXIST);
        }
        return order;
    }

    // 校验订单归属当前登录用户
    private void ensureOrderOwnedByCurrentUser(Order order) {
        Integer currentUserId = getCurrentUserIdFromSession();
        if (!order.getUserId().equals(currentUserId)) {
            throw getCustomException(ExceptionCodeEnum.ORDER_NOT_EXIST);
        }
    }
}
